#version 430 core

#define GRID_SIZE_X 64
#define GRID_SIZE_Y 64

layout(local_size_x=16, local_size_y=16) in;

layout(binding=0, r32f) uniform readonly image2D levelSetImage;
layout(binding=1, r32i) uniform iimage2D nodeIndexImage;

layout(binding=0, offset=0) uniform atomic_uint counter;

layout(binding=3) coherent buffer nodePositionBuffer {
	uvec2 nodePositions[];
};

void main(void)
{
	// one invocation per node
	ivec2 gid = ivec2(gl_GlobalInvocationID.xy);
	if (gid.x <= GRID_SIZE_X && gid.y <= GRID_SIZE_Y)
	{
		if (imageLoad(nodeIndexImage, gid).x == 0) // candidate for being part of the system
		{
			bvec2 onBoundaryTemp = equal(gid, ivec2(0,0)) || equal(gid, ivec2(GRID_SIZE_X, GRID_SIZE_Y));
			bool  onBoundary = onBoundaryTemp.x || onBoundaryTemp.y;
			bool inFluid = imageLoad(levelSetImage, gid).x <= 0;
			int newNodeIndex;
			if (!inFluid) // in air or in solid
			{
				newNodeIndex = -1 - int(onBoundary); // -1 for air, -2 for solid
			}
			else
			{
				newNodeIndex = int(atomicCounterIncrement(counter));
				nodePositions[newNodeIndex] = gl_GlobalInvocationID.xy;
			}
			imageStore(nodeIndexImage, gid, ivec4(newNodeIndex,0,0,1));
		}
	}
}